home *** CD-ROM | disk | FTP | other *** search
- /*
- * SFtoSpr - Star Fighter 3000 graphics converter
- * Directory scan
- * Copyright (C) 2000 Chris Bazley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public Licence as published by
- * the Free Software Foundation; either version 2 of the Licence, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public Licence for more details.
- *
- * You should have received a copy of the GNU General Public Licence
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /* ANSI library files */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdbool.h>
- #include <assert.h>
-
- /* RISC OS library files */
- #include "kernel.h"
- #include "wimp.h"
- #include "toolbox.h"
- #include "event.h"
- #include "wimplib.h"
- #include "window.h"
- #include "gadgets.h"
- #include "flex.h"
-
- /* My library files */
- #include "err.h"
- #include "msgtrans.h"
- #include "hourglass.h"
- #include "SprFormats.h"
- #include "SFformats.h"
- #include "FedCompMT.h"
- #include "ViewsMenu.h"
- #include "Loader.h"
- #include "Macros.h"
- #include "NoBudge.h"
- #include "RoundRobin.h"
- #include "LoadSaveMT.h"
- #include "AbortFop.h"
-
- /* Local headers */
- #include "SFgfxconv.h"
- #include "Utils.h"
- #include "Main.h"
- #include "Scan.h"
-
- /* gadget IDs */
- #define SCAN_ACTIVITY 0x0c
- #define SCAN_PATH 0x0d
- #define SCAN_SCANNED 0x0a
- #define SCAN_CONVERTED 0x0b
- #define SCAN_ABORT 0x01
- #define SCAN_SKIP 0x02
- #define SCAN_RESTART 0x03
- #define SCAN_FOURTHBUTTON 0x04
- #define SCAN_MESSAGE 0x05
-
- #define SCAN_PHASE_DUMMY -3
- #define SCAN_PHASE_ERROR -2
- #define SCAN_PHASE_PAUSE -1
- #define SCAN_PHASE_IDLE 0
- #define SCAN_PHASE_SCANNING 1
- #define SCAN_PHASE_LOAD 2
- #define SCAN_PHASE_LOADANIMS 3
- #define SCAN_PHASE_CONVERT 4
- #define SCAN_PHASE_SAVE 5
- #define SCAN_PHASE_SAVEANIMS 6
-
- typedef struct
- { int loadaddr;
- int execaddr;
- int length;
- int attributes;
- int objecttype;
- int filetype;
- char filename[256];
- } OSGBPBblock;
-
- typedef struct _ScanData
- {
- ObjectId window_id; /* dialogue window */
- char *loadroot;
- char *saveroot;
- int phase; /* what is going on */
- int level;
- int numchecked;
- int numoutput;
-
- char *loadpath;
-
- void *input_buffer; /* flex block */
- int input_type;
- SF_MapTilesSetHdr anims;
-
- bool conv_to_sf3000;
- bool conv_to_tile;
- void *output_buffer; /* flex block */
- int output_type;
-
- char *savepath; /* "root"+"relative_dir"+"leafname" */
-
- char *relativedir;
-
- int *position; /* position on each level of tree */
-
- int return_phase; /* for pause, error */
- /* preserved data for retry */
- int retry_numchecked;
- int retry_numoutput;
- int retry_position;
- FILE **thread_state;
- char return_action[16];
- } ScanData;
-
- /* ----------------------------------------------------------------------- */
- /* Function prototypes */
-
- static void _Scan_displayerror(ScanData *scan_data, char *errormessage);
- static void _Scan_displayprogress(ScanData *scan_data);
- static void _Scan_updatewindow(ScanData *scan_data, const char *action, const char *filepath);
- static int _Scan_scanforfile(ScanData *scan_data);
- static int _Scan_convertdata(ScanData *scan_data);
- static int _Scan_loadfile(ScanData *scan_data, const volatile bool *time_up);
- static int _Scan_loadanimsfile(ScanData *scan_data);
- static int _Scan_savefile(ScanData *scan_data, const volatile bool *time_up);
- static int _Scan_saveanimsfile(ScanData *scan_data);
- static RoundRobinHandler _Scan_pollhandler;
- static ToolboxEventHandler _Scan_buttonhandler, _Scan_deletedhandler;
-
- /* ----------------------------------------------------------------------- */
- /* Public functions */
-
- ObjectId Scan_create(char *newloadroot, char *newsaveroot, bool tosf3000)
- {
- char *titletok, *convnametok;
- ScanData *newscan_data;
-
- /* Allocate space for thread data */
- newscan_data = malloc(sizeof(ScanData));
- if(newscan_data == NULL)
- MG_RETV("NoMem", NULL_ObjectId) /* failure */
-
- /* Create scan progress window */
- if(E(toolbox_create_object(0, "Scan", &newscan_data->window_id)))
- goto errexit1;
-
- /* Add to window list */
- if(tosf3000) {
- convnametok = "ScanSprSFList";
- titletok = "ScanSprSFTitle";
- }
- else {
- convnametok = "ScanSFSprList";
- titletok = "ScanSFSprTitle";
- }
- if(E(window_set_title(0, newscan_data->window_id, msgs_lookup(titletok))))
- goto errexit2;
- if(E(ViewsMenu_add(newscan_data->window_id, msgs_lookup_sub1(convnametok, tail(newloadroot, 3)), "")))
- goto errexit2;
-
- /* register to receive null polls */
- if(E(RoundRobin_register(_Scan_pollhandler, newscan_data)))
- goto errexit3;
-
- /* Allocate memory */
- newscan_data->loadpath = NULL;
- newscan_data->savepath = NULL;
- newscan_data->loadroot = copystring(newloadroot);
- if(newscan_data->loadroot == NULL)
- goto errexit4;
- newscan_data->saveroot = copystring(newsaveroot);
- if(newscan_data->saveroot == NULL)
- goto errexit5;
- newscan_data->relativedir = copystring("");
- if(newscan_data->relativedir == NULL)
- goto errexit6;
- newscan_data->position = malloc(sizeof(int));
- if(newscan_data->position == NULL)
- goto errexit7;
-
- /* Unallocated flex anchors */
- newscan_data->input_buffer = NULL;
- newscan_data->output_buffer = NULL;
-
- /* Initialise thread variables */
- newscan_data->level = 0;
- newscan_data->position[newscan_data->level] = 0;
- newscan_data->numchecked = 0;
- newscan_data->numoutput = 0;
- newscan_data->conv_to_sf3000 = tosf3000; /* conversion mode */
- newscan_data->phase = SCAN_PHASE_SCANNING;
-
- /* Register event handlers
- Note that ObjectDeleted handler is registered AFTER anything that could cause an error and therefore premature deletion!
- */
- if(!E(event_register_toolbox_handler(newscan_data->window_id, ActionButton_Selected, _Scan_buttonhandler, newscan_data))
- && !E(event_register_toolbox_handler(newscan_data->window_id, Toolbox_ObjectDeleted, _Scan_deletedhandler, newscan_data))) {
-
- /* Set up window */
- _Scan_displayprogress(newscan_data);
- _Scan_updatewindow(newscan_data, msgs_lookup("ScanTOpen"), newscan_data->loadroot);
- RE(button_set_value(0, newscan_data->window_id, SCAN_CONVERTED, "0"))
- RE(button_set_value(0, newscan_data->window_id, SCAN_SCANNED, "0"))
-
- return newscan_data->window_id; /* initialisation successful */
- }
-
- errexit7:
- free(newscan_data->relativedir);
- errexit6:
- free(newscan_data->saveroot);
- errexit5:
- free(newscan_data->loadroot);
- errexit4:
- RoundRobin_deregister(_Scan_pollhandler, newscan_data);
- errexit3:
- RE(ViewsMenu_remove(newscan_data->window_id))
- errexit2:
- RE(toolbox_delete_object(0, newscan_data->window_id))
- errexit1:
- free(newscan_data);
- return NULL_ObjectId; /* failure */
- }
-
- /* ----------------------------------------------------------------------- */
- /* Private functions */
-
- static void _Scan_pollhandler(void *handle, const volatile bool *time_up)
- {
- ScanData *scan_data = (ScanData *)handle;
- int new_phase = SCAN_PHASE_DUMMY;
-
- err_suppress_errors(); /* suppress and record errors */
-
- switch(scan_data->phase) {
- case SCAN_PHASE_SCANNING:
- new_phase = _Scan_scanforfile(scan_data);
- break;
-
- case SCAN_PHASE_LOAD:
- new_phase = _Scan_loadfile(scan_data, time_up);
- break;
-
- case SCAN_PHASE_LOADANIMS:
- new_phase = _Scan_loadanimsfile(scan_data);
- break;
-
- case SCAN_PHASE_CONVERT:
- new_phase = _Scan_convertdata(scan_data);
- break;
-
- case SCAN_PHASE_SAVE:
- new_phase = _Scan_savefile(scan_data, time_up);
- break;
-
- case SCAN_PHASE_SAVEANIMS:
- new_phase = _Scan_saveanimsfile(scan_data);
- break;
- }
-
- if(new_phase != SCAN_PHASE_DUMMY)
- scan_data->phase = new_phase;
-
- if(new_phase == SCAN_PHASE_ERROR) {
- /* free any allocated buffers */
- if(scan_data->input_buffer != NULL)
- flex_free((flex_ptr)&scan_data->input_buffer);
- if(scan_data->output_buffer != NULL)
- flex_free((flex_ptr)&scan_data->output_buffer);
-
- /* turn progress window into error box */
- _Scan_displayerror(scan_data, err_dump_suppressed()->errmess);
- RoundRobin_deregister(_Scan_pollhandler, handle); /* cease null-polling */
- }
- else
- err_dump_suppressed(); /* Allow up-front errors again */
- }
-
- /* ----------------------------------------------------------------------- */
-
- static int _Scan_buttonhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
- {
- ScanData *scan_data = (ScanData *)handle;
- char *new_ptr;
- if(scan_data->phase != SCAN_PHASE_ERROR) {
-
- switch(id_block->self_component) {
- case SCAN_ABORT: /* Abort */
- RE(toolbox_delete_object(0,scan_data->window_id))
- return 1; /* claim event */
-
- case SCAN_FOURTHBUTTON: /* Pause/Continue */
- if(scan_data->phase == SCAN_PHASE_PAUSE) {
- /* unpause it */
- RE(actionbutton_set_text(0, scan_data->window_id, SCAN_FOURTHBUTTON, (char *)msgs_lookup("ScanBPause")))
- RE(gadget_set_help_message(0, scan_data->window_id, SCAN_FOURTHBUTTON, (char *)msgs_lookup("ScanHPause")))
- RE(button_set_value(0, scan_data->window_id, SCAN_ACTIVITY, scan_data->return_action))
- scan_data->phase = scan_data->return_phase;
- RE(RoundRobin_register(_Scan_pollhandler, handle)) /* resume null-polling */
- }
- else {
- /* pause it */
- RE(actionbutton_set_text(0, scan_data->window_id, SCAN_FOURTHBUTTON, (char *)msgs_lookup("ScanBCont")))
- RE(gadget_set_help_message(0, scan_data->window_id, SCAN_FOURTHBUTTON, (char *)msgs_lookup("ScanHCont")))
- RE(button_get_value(0, scan_data->window_id, SCAN_ACTIVITY, scan_data->return_action, sizeof(scan_data->return_action), NULL))
- RE(button_set_value(0, scan_data->window_id, SCAN_ACTIVITY, (char *)msgs_lookup("ScanTPaused")))
- scan_data->return_phase = scan_data->phase;
- scan_data->phase = SCAN_PHASE_PAUSE;
- RoundRobin_deregister(_Scan_pollhandler, handle); /* cease null-polling */
- }
- return 1; /* claim event */
-
- default:
- return 0; /* pass event on */
- }
- }
- else {
- /* Houston, we have a problem */
- switch(id_block->self_component) {
- case SCAN_ABORT:/* Abort */
- RE(toolbox_delete_object(0,scan_data->window_id))
- return 1; /* claim event */
-
- case SCAN_SKIP:/* Skip to next file */
- _Scan_displayprogress(scan_data);
- scan_data->phase = SCAN_PHASE_SCANNING;
- RE(RoundRobin_register(_Scan_pollhandler, handle)) /* resume null-polling */
- return 1; /* claim event */
-
- case SCAN_RESTART:/* Restart */
- scan_data->level = 0;
- scan_data->position[scan_data->level] = 0;
- scan_data->numchecked = 0;
- scan_data->numoutput = 0;
- new_ptr = copystring("");
- if(new_ptr == NULL)
- return 1; /* claim event */
- free(scan_data->relativedir);
- scan_data->relativedir = new_ptr;
- _Scan_displayprogress(scan_data);
- _Scan_updatewindow(scan_data,msgs_lookup("ScanTOpen"),scan_data->loadroot);
- RE(button_set_value(0, scan_data->window_id, SCAN_SCANNED, "0"))
- RE(button_set_value(0, scan_data->window_id, SCAN_CONVERTED, "0"))
-
- scan_data->phase = SCAN_PHASE_SCANNING;
- RE(RoundRobin_register(_Scan_pollhandler, handle)) /* resume null-polling */
- return 1;
-
- case SCAN_FOURTHBUTTON:/* Retry */
- _Scan_displayprogress(scan_data);
- scan_data->numchecked = scan_data->retry_numchecked;
- {
- char num[16];
- #ifndef OLD_SCL_STUBS
- snprintf(num, sizeof(num), "%d", scan_data->numchecked);
- #else
- sprintf(num, "%d", scan_data->numchecked);
- #endif
- RE(button_set_value(0, scan_data->window_id, SCAN_SCANNED, num))
- }
- scan_data->numoutput = scan_data->retry_numoutput;
- {
- char num[16];
- #ifndef OLD_SCL_STUBS
- snprintf(num, sizeof(num), "%d", scan_data->numoutput);
- #else
- sprintf(num, "%d", scan_data->numoutput);
- #endif
- RE(button_set_value(0, scan_data->window_id, SCAN_CONVERTED, num))
- }
- scan_data->position[scan_data->level] = scan_data->retry_position;
- scan_data->phase = SCAN_PHASE_SCANNING;
- RE(RoundRobin_register(_Scan_pollhandler, handle)) /* resume null-polling */
- return 1; /* claim event */
-
- default:
- return 0; /* event not handled */
- }
- }
- }
-
- /* ----------------------------------------------------------------------- */
-
- static int _Scan_deletedhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
- {
- ScanData *scan_data = (ScanData *)handle;
-
- if(scan_data->phase != SCAN_PHASE_ERROR
- && scan_data->phase != SCAN_PHASE_PAUSE)
- RoundRobin_deregister(_Scan_pollhandler, handle); /* if we were null polling then stop */
-
- RE(event_deregister_toolbox_handler(id_block->self_id, ActionButton_Selected, _Scan_buttonhandler, handle))
- RE(event_deregister_toolbox_handler(id_block->self_id, Toolbox_ObjectDeleted, _Scan_deletedhandler, handle))
-
- RE(ViewsMenu_remove(id_block->self_id))
-
- /* free all memory for this op */
- if(scan_data->input_buffer != NULL)
- flex_free((flex_ptr)&scan_data->input_buffer);
- if(scan_data->output_buffer != NULL)
- flex_free((flex_ptr)&scan_data->output_buffer);
-
- free(scan_data->position);
- free(scan_data->loadpath);
- free(scan_data->savepath);
- free(scan_data->relativedir);
-
- /* and finally... */
- free(scan_data->loadroot);
- free(scan_data->saveroot);
-
- /* free state and close down any running thread */
- if(scan_data->thread_state != NULL) {
- if(scan_data->phase == SCAN_PHASE_LOAD
- || (scan_data->phase == SCAN_PHASE_PAUSE && scan_data->return_phase == SCAN_PHASE_LOAD)
- || scan_data->phase == SCAN_PHASE_SAVE
- || (scan_data->phase == SCAN_PHASE_PAUSE && scan_data->return_phase == SCAN_PHASE_SAVE))
- abort_file_op(&scan_data->thread_state);
- }
-
- free(scan_data);
- return 1;
- }
-
- /* ----------------------------------------------------------------------- */
-
- static void _Scan_displayerror(ScanData *scan_data, char *errormessage)
- {
- /* opens progress window to centre of screen at expanded size and sets up buttons */
- WindowShowObjectBlock wsob;
- int cernX,cernY;
- RE(showgadget(scan_data->window_id, SCAN_SKIP));
- /* Can't 'Skip' if stuck at end of directory (error leaving it),
- or if scan_data->position wasn't updated (error calling OS_GBPB) */
- RE(set_gadget_faded(
- (scan_data->position[scan_data->level] == -1 || scan_data->position[scan_data->level] == scan_data->retry_position),
- scan_data->window_id,
- SCAN_SKIP
- ));
- RE(showgadget(scan_data->window_id, SCAN_RESTART));
- RE(actionbutton_set_text(0, scan_data->window_id, SCAN_FOURTHBUTTON, (char *)msgs_lookup("ScanBRetry")));
- RE(gadget_set_help_message(0, scan_data->window_id, SCAN_FOURTHBUTTON, (char *)msgs_lookup("ScanHRetry")));
- RE(button_set_value(0, scan_data->window_id, SCAN_MESSAGE, errormessage));
- /* Alter visible area and centre */
- RE(getscreencentre(&cernX, &cernY))
- wsob.visible_area.xmin = cernX - (736/2);
- wsob.visible_area.ymax = cernY + (596/2);
- wsob.visible_area.xmax = cernX + (736/2);
- wsob.visible_area.ymin = cernY - (596/2);
- wsob.xscroll = 0;wsob.yscroll = 0;
- wsob.behind = -1; /* top of stack */
- RE(ViewsMenu_show_object(0, scan_data->window_id, Toolbox_ShowObject_FullSpec, &wsob, 0, 0))
- /* N.B. consider the fact that window may be iconised */
- }
-
- /* ----------------------------------------------------------------------- */
-
- static void _Scan_displayprogress(ScanData *scan_data)
- {
- WimpGetWindowInfoBlock windowinfo;
- WindowShowObjectBlock wsob;
- /* reduces progress window to normal size, restores normal buttons */
- RE(hidegadget(scan_data->window_id, SCAN_SKIP))
- RE(hidegadget(scan_data->window_id, SCAN_RESTART))
- if(scan_data->phase == SCAN_PHASE_PAUSE) {
- RE(actionbutton_set_text(0, scan_data->window_id, SCAN_FOURTHBUTTON, (char *)msgs_lookup("ScanBCont")))
- RE(gadget_set_help_message(0, scan_data->window_id, SCAN_FOURTHBUTTON, (char *)msgs_lookup("ScanHCont")))
- }
- else {
- RE(actionbutton_set_text(0, scan_data->window_id, SCAN_FOURTHBUTTON, (char *)msgs_lookup("ScanBPause")))
- RE(gadget_set_help_message(0, scan_data->window_id, SCAN_FOURTHBUTTON, (char *)msgs_lookup("ScanHPause")))
- }
- /* Alter visible area but not position */
- RE(window_get_wimp_handle(0, scan_data->window_id, &windowinfo.window_handle))
- RE(wimp_get_window_info_no_icon_data(&windowinfo))
- wsob.visible_area.xmin = windowinfo.window_data.visible_area.xmin;
- wsob.visible_area.ymax = windowinfo.window_data.visible_area.ymax;
- wsob.visible_area.xmax = windowinfo.window_data.visible_area.xmin + 620;
- wsob.visible_area.ymin = windowinfo.window_data.visible_area.ymax - 252;
- wsob.xscroll = 60;
- wsob.yscroll = 0;
- wsob.behind = windowinfo.window_data.behind;
- RE(toolbox_show_object(0, scan_data->window_id, Toolbox_ShowObject_FullSpec, &wsob, 0, 0))
- /* N.B. window can never be iconised at this point (function called when just created, or as result of button press) */
- }
-
- /* ----------------------------------------------------------------------- */
-
- static void _Scan_updatewindow(ScanData *scan_data, const char *action, const char *filepath)
- {
- /* Only update action text if not the same */
- {
- char current_action[16];
- RE(button_get_value(0, scan_data->window_id, SCAN_ACTIVITY, current_action, sizeof(current_action), NULL))
- if(strcmp(current_action, action) != 0)
- RE(button_set_value(0, scan_data->window_id, SCAN_ACTIVITY, (char *)action))
- }
-
- /* Whereas file paths are v. unlikely to be the same (impossible?) */
- RE(button_set_value(0, scan_data->window_id, SCAN_PATH, (char *)filepath))
- }
-
- /* ----------------------------------------------------------------------- */
-
- static int _Scan_scanforfile(ScanData *scan_data) {
- OSGBPBblock GBPB_buffer;
- _kernel_swi_regs regs;
-
- scan_data->retry_position = scan_data->position[scan_data->level];
- scan_data->retry_numchecked = scan_data->numchecked;
- scan_data->retry_numoutput = scan_data->numoutput;
-
- /* construct input and output directory paths */
- #ifndef OLD_SCL_STUBS
- char input_dir[strlen(scan_data->loadroot)+1+strlen(scan_data->relativedir)+1];
- char output_dir[strlen(scan_data->saveroot)+1+strlen(scan_data->relativedir)+1];
- #else
- char *input_dir = malloc(strlen(scan_data->loadroot)+1+strlen(scan_data->relativedir)+1);
- if(input_dir == NULL)
- RG_RETV("NoMem", SCAN_PHASE_ERROR)
-
- char *output_dir = malloc(strlen(scan_data->saveroot)+1+strlen(scan_data->relativedir)+1);
- if(output_dir == NULL) {
- free(input_dir);
- RG_RETV("NoMem", SCAN_PHASE_ERROR)
- }
- #endif
-
- if(strcmp(scan_data->relativedir, "") != 0) {
- sprintf(input_dir, "%s.%s", scan_data->loadroot, scan_data->relativedir);
- sprintf(output_dir, "%s.%s", scan_data->saveroot, scan_data->relativedir);
- }
- else {
- strcpy(input_dir, scan_data->loadroot);
- strcpy(output_dir, scan_data->saveroot);
- }
-
- /* get next file */
- regs.r[0] = 12; /* read entries and full info with filetype from given dir */
- regs.r[1] = (int)input_dir; /* pointer to dir name */
- regs.r[2] = (int)&GBPB_buffer; /* pointer to buffer */
- regs.r[3] = 1; /* objects to read */
- regs.r[4] = scan_data->position[scan_data->level]; /* where to start */
- regs.r[5] = sizeof(OSGBPBblock); /* buffer length */
- regs.r[6] = 0; /* any filename */
- if(E(_kernel_swi(OS_GBPB, ®s, ®s))) {
- #ifdef OLD_SCL_STUBS
- free(input_dir);
- free(output_dir);
- #endif
- return SCAN_PHASE_ERROR;
- }
- scan_data->position[scan_data->level] = regs.r[4];
-
- /* check for end of directory */
- if(regs.r[4] == -1) {
- /* =============================================== */
- /* Reached end of this directory, so go up a level */
-
- _Scan_updatewindow(scan_data, msgs_lookup("ScanTLeave"), output_dir);
- #ifdef OLD_SCL_STUBS
- free(input_dir);
- free(output_dir);
- #endif
-
- if(scan_data->level == 0) {
- /* in root dir, so finish */
- RE(toolbox_delete_object(0, scan_data->window_id))
- return SCAN_PHASE_IDLE;
- }
-
- /* WE HAVE TO BE VERY CAREFUL NOT TO BUGGER UP RELATIVEDIR OR POSITION[], IN ANY CIRCUMSTANCES! */
- {
- char *newstring;
- {
- /* Find last full-stop in directory pathname (relative to root) */
- int stoplen;
- char *laststop = strrchr(scan_data->relativedir, '.');
- if(laststop == NULL)
- /* Could not find full-stop so relativedir is just leafname */
- laststop = scan_data->relativedir;
- stoplen = (unsigned int)laststop - (unsigned int)scan_data->relativedir;
- newstring = malloc(stoplen + 1);
- if(newstring == NULL)
- RG_RETV("NoMem", SCAN_PHASE_ERROR)
- strncpy(newstring, scan_data->relativedir, stoplen);
- laststop = (char *)((unsigned int)newstring + stoplen);
- *laststop = 0;
- }
- /* Retract array holding our position on each level */
- {
- int *newptr;
- newptr = realloc(scan_data->position, (scan_data->level-1+1) * sizeof(int));
- if(newptr == NULL) {
- free(newstring);
- RG_RETV("NoMem", SCAN_PHASE_ERROR)
- }
-
- /* Now we're absolutely certain we can proceed up tree, its safe to bugger around with position and relativedir */
- scan_data->level--;
- free(scan_data->relativedir);
- scan_data->relativedir = newstring;
- scan_data->position = newptr;
- }
- }
-
- return SCAN_PHASE_SCANNING;
- } /* if end of directory */
-
- /* ================================================================ */
- /* There are further objects to scan within current directory level */
- if(regs.r[3] != 1) {
- #ifdef OLD_SCL_STUBS
- free(input_dir);
- free(output_dir);
- #endif
- R_RETV("IntErrScan", SCAN_PHASE_ERROR)
- }
-
- free(scan_data->loadpath);
- scan_data->loadpath = malloc(strlen(input_dir)+1+strlen(GBPB_buffer.filename)+1);
- free(scan_data->savepath);
- scan_data->savepath = malloc(strlen(output_dir)+1+strlen(GBPB_buffer.filename)+1);
- if(scan_data->loadpath == NULL || scan_data->savepath == NULL) {
- #ifdef OLD_SCL_STUBS
- free(input_dir);
- free(output_dir);
- #endif
- RG_RETV("NoMem", SCAN_PHASE_ERROR)
- }
-
- /* make full path for file to load as */
- sprintf(scan_data->loadpath, "%s.%s", input_dir, GBPB_buffer.filename);
- #ifdef OLD_SCL_STUBS
- free(input_dir);
- #endif
-
- /* make full path for file to save as */
- sprintf(scan_data->savepath, "%s.%s", output_dir, GBPB_buffer.filename);
- #ifdef OLD_SCL_STUBS
- free(output_dir);
- #endif
-
- scan_data->input_type = GBPB_buffer.filetype;
- switch(GBPB_buffer.objecttype) {
-
- case 1:/* object is file - check whether we shall load it */
- scan_data->numchecked++;
- {
- char num[16];
- #ifndef OLD_SCL_STUBS
- snprintf(num, sizeof(num), "%d", scan_data->numchecked);
- #else
- sprintf(num, "%d", scan_data->numchecked);
- #endif
- RE(button_set_value(0, scan_data->window_id, SCAN_SCANNED, num))
- }
-
- if(((scan_data->input_type == FILETYPE_MAPTILES || scan_data->input_type == FILETYPE_PLANETS) && !scan_data->conv_to_sf3000)
- || (scan_data->input_type == FILETYPE_SPRITE && scan_data->conv_to_sf3000)) {
- scan_data->thread_state = NULL;
- return SCAN_PHASE_LOAD;
- }
- else {
- /* file of no interest */
- _Scan_updatewindow(scan_data,msgs_lookup("ScanTIgnore"), scan_data->loadpath);
- return SCAN_PHASE_SCANNING;
- }
- break;
-
- case 2:/* Object is directory - go down a level */
- case 3:/* or image file */
- _Scan_updatewindow(scan_data, msgs_lookup("ScanTOpen"), scan_data->loadpath);
-
- /* WE HAVE TO BE VERY CAREFUL NOT TO BUGGER UP RELATIVEDIR OR POSITION[], IN ANY CIRCUMSTANCES! */
- {
- char *newstring = malloc(strlen(scan_data->relativedir) + 1 + strlen(GBPB_buffer.filename) + 1);
- if(newstring == NULL)
- RG_RETV("NoMem", SCAN_PHASE_ERROR)
- if(strcmp(scan_data->relativedir, "") != 0)
- sprintf(newstring, "%s.%s", scan_data->relativedir, GBPB_buffer.filename);
- else
- strcpy(newstring, GBPB_buffer.filename);
- {
- /* Extend array holding our position on each level */
- int *newptr = realloc(scan_data->position, (scan_data->level+1+1) * sizeof(int));
- if(newptr == NULL) {
- free(newstring);
- RG_RETV("NoMem", SCAN_PHASE_ERROR)
- }
- /* Now we're absolutely certain we can proceed down tree, its safe to bugger around with position and relativedir */
- scan_data->level++;
- free(scan_data->relativedir);
- scan_data->relativedir = newstring;
- scan_data->position = newptr;
- scan_data->position[scan_data->level] = 0; /* start at beginning of dir */
- }
- }
- break;
-
- } /* what object type */
- return SCAN_PHASE_SCANNING;
- }
-
- /* ----------------------------------------------------------------------- */
-
- static int _Scan_loadanimsfile(ScanData *scan_data)
- {
- /* Load any textfile animations */
- #ifndef NDEBUG
- _kernel_oscli("report Loading animations file");
- #endif
-
- #ifndef OLD_SCL_STUBS
- char anifilename[strlen(scan_data->loadpath)+4+1];
- #else
- char *anifilename = malloc(strlen(scan_data->loadpath)+4+1);
- if(anifilename == NULL)
- RG_RETV("NoMem", SCAN_PHASE_ERROR) /* failure */
- #endif
- sprintf(anifilename, "%s/ani", scan_data->loadpath);
-
- _Scan_updatewindow(scan_data, msgs_lookup("ScanTLoad"), anifilename);
-
- SF_MapTilesSetHdr *temp_anims_ptr = &scan_data->anims;
- _kernel_oserror *err = load_animsfilepath(anifilename, &temp_anims_ptr, true);
- #ifdef OLD_SCL_STUBS
- free(anifilename);
- #endif
- if(err != NULL) {
- err_report(err->errnum, msgs_lookup_sub1("LoadFail", err->errmess));
- return SCAN_PHASE_ERROR; /* failure */
- } else {
- return SCAN_PHASE_CONVERT; /* success */
- }
- }
- /* ----------------------------------------------------------------------- */
-
- static int _Scan_loadfile(ScanData *scan_data, const volatile bool *time_up)
- {
- _kernel_oserror *err;
-
- if(scan_data->thread_state == NULL) {
- _Scan_updatewindow(scan_data, msgs_lookup("ScanTLoad"), scan_data->loadpath);
- }
-
- assert(scan_data->input_type == FILETYPE_MAPTILES || scan_data->input_type == FILETYPE_PLANETS || scan_data->input_type == FILETYPE_SPRITE);
-
- if(scan_data->input_type == FILETYPE_SPRITE)
- err = load_fileM(scan_data->loadpath, (flex_ptr)&scan_data->input_buffer, time_up, &scan_data->thread_state, true);
- else
- err = load_compressedM(scan_data->loadpath, (flex_ptr)&scan_data->input_buffer, time_up, &scan_data->thread_state);
-
- if(err != NULL) {
- scan_data->input_buffer = NULL;
- err_report(err->errnum, msgs_lookup_sub1("LoadFail", err->errmess));
- return SCAN_PHASE_ERROR; /* fail */
- }
-
- if(scan_data->thread_state == NULL) {
- /* Have finished loading this file */
- #ifndef NDEBUG
- _kernel_oscli("report Have finished loading");
- #endif
-
- if(scan_data->input_type == FILETYPE_SPRITE) {
- /* Does the spritefile contain either valid planets or tiles? */
- bool found_tile = contains_valid_tiles((spriteareaheader **)&scan_data->input_buffer);
- bool found_pla = contains_valid_planets((spriteareaheader **)&scan_data->input_buffer);
- if(!found_tile && !found_pla) {
- /* This Sprite file is of no interest whatever */
- flex_free((flex_ptr)&scan_data->input_buffer);
- return SCAN_PHASE_SCANNING;
- }
- if(found_pla && found_tile) {
- M("AutoDouble"); /* confusion overload */
- return SCAN_PHASE_ERROR;
- }
- scan_data->conv_to_tile = found_tile;
-
- if(scan_data->conv_to_sf3000 && found_tile)
- return SCAN_PHASE_LOADANIMS; /* new phase! */
- }
- return SCAN_PHASE_CONVERT; /* success */
- }
- else {
- /* We will have to come back another time */
- //unsigned int perc;
- #ifndef NDEBUG
- _kernel_oscli("report Loading incomplete");
- #endif
- //if(scan_data->input_type == FILETYPE_SPRITE)
- // perc = get_loadsave_perc(&scan_data->thread_state);
- //else
- // perc = get_decomp_perc(&scan_data->thread_state);
- return SCAN_PHASE_LOAD; /* success */
- }
- }
-
- /* ----------------------------------------------------------------------- */
-
- static int _Scan_convertdata(ScanData *scan_data)
- {
- _Scan_updatewindow(scan_data, msgs_lookup("ScanTConvert"), scan_data->loadpath);
-
- switch(scan_data->input_type) {
- case FILETYPE_MAPTILES:
- if(!tiles_to_sprites((SF_MapTilesSetHdr **)&scan_data->input_buffer, (spriteareaheader **)&scan_data->output_buffer)) {
- scan_data->output_buffer = NULL;
- return SCAN_PHASE_ERROR;
- }
-
- /* Copy the tiles file header before discarding buffer */
- nobudge_register(256);
- memcpy(&scan_data->anims, scan_data->input_buffer, sizeof(SF_MapTilesSetHdr));
- nobudge_deregister();
- scan_data->output_type = FILETYPE_SPRITE;
- break;
-
- case FILETYPE_PLANETS:
- if(!planets_to_sprites((SF_PlanetsSetHdr **)&scan_data->input_buffer, (spriteareaheader **)&scan_data->output_buffer)) {
- scan_data->output_buffer = NULL;
- return SCAN_PHASE_ERROR;
- }
- scan_data->output_type = FILETYPE_SPRITE;
- break;
-
- case FILETYPE_SPRITE:
- /* Verify sprite area we will be generating output from */
- if(verify_spriteareas) {
- nobudge_register(256);
- if(E(_swix(OS_SpriteOp, _INR(0,1), 17+256, scan_data->input_buffer))) {
- nobudge_deregister();
- return SCAN_PHASE_ERROR;
- }
- nobudge_deregister();
- }
-
- /* Convert to MapTiles or Planets? */
- if(scan_data->conv_to_tile) {
- /* Convert to MapTiles set */
- if(!sprites_to_tiles((spriteareaheader **)&scan_data->input_buffer, (SF_MapTilesSetHdr **)&scan_data->output_buffer, true)) {
- scan_data->output_buffer = NULL;
- return SCAN_PHASE_ERROR;
- }
- /* Check the animations (must wait til we know last tile num) */
- /*if(!check_animations((SF_MapTilesSetHdr *)scan_data->output_buffer))
- goto poll_err;*/
- scan_data->output_type = FILETYPE_MAPTILES;
- }
- else {
- /* Convert to Planets set */
- if(!sprites_to_planets((spriteareaheader **)&scan_data->input_buffer, (SF_PlanetsSetHdr **)&scan_data->output_buffer, true)) {
- scan_data->output_buffer = NULL;
- return SCAN_PHASE_ERROR;
- }
- scan_data->output_type = FILETYPE_PLANETS;
- }
- break;
- }
- flex_free((flex_ptr)&scan_data->input_buffer);
- return SCAN_PHASE_SAVE;
- }
-
- /* ----------------------------------------------------------------------- */
-
- static int _Scan_saveanimsfile(ScanData *scan_data)
- {
- #ifndef NDEBUG
- _kernel_oscli("report Saving animations file");
- #endif
-
- #ifndef OLD_SCL_STUBS
- char ani_file_name[strlen(scan_data->savepath) + 4 + 1];
- #else
- char *ani_file_name = malloc(strlen(scan_data->savepath) + 4 + 1);
- if(ani_file_name == NULL)
- RG_RETV("NoMem", SCAN_PHASE_ERROR) /* failure */
- #endif
- sprintf(ani_file_name, "%s/ani", scan_data->savepath);
-
- _Scan_updatewindow(scan_data, msgs_lookup("ScanTSave"), ani_file_name);
-
- _kernel_oserror *err = save_animsfile(ani_file_name, &scan_data->anims);
- #ifdef OLD_SCL_STUBS
- free(ani_file_name);
- #endif
- if(err != NULL) {
- err_report(err->errnum, msgs_lookup_sub1("SaveFail", err->errmess));
- return SCAN_PHASE_ERROR; /* failure */
- } else {
- return SCAN_PHASE_SCANNING; /* success */
- }
- }
-
- /* ----------------------------------------------------------------------- */
-
- static int _Scan_savefile(ScanData *scan_data, const volatile bool *time_up)
- {
- if(scan_data->thread_state == NULL) {
- _Scan_updatewindow(scan_data, msgs_lookup("ScanTSave"), scan_data->savepath);
-
- char *ourdirstart, *chopsubdir;
- _kernel_osfile_block kosfb;
-
- /* Ensure that entirety of output file path exists */
- /* saveroot = "RAM::0.$.Landscapes"
- relativedir = "Planets"
- savepath = "RAM::0.$.Landscapes.Planets.Earth" */
- ourdirstart = (char *)(
- (unsigned int)scan_data->savepath
- + ((unsigned int)strrchr(scan_data->saveroot, '.')+1 - (unsigned int)scan_data->saveroot)
- ); /* find saveroot leaf ("Landscapes") in savepath */
- /* ourdirstart = "Landscapes.Planets.Earth" */
- chopsubdir = strchr(ourdirstart, '.'); /* end of head subdirectory */
- while(chopsubdir != NULL) {
- *chopsubdir=0;
- /* savepath = {"RAM::0.$.Landscapes", "RAM::0.$.Landscapes.Planets"} */
-
- /* Create subdirectory */
- kosfb.start = 0; /* default number of entries */
- if(_kernel_osfile(8, scan_data->savepath, &kosfb) == _kernel_ERROR) {
- _kernel_oserror *e = _kernel_last_oserror();
- err_report(e->errnum, msgs_lookup_sub1("DirFail", e->errmess));
- return SCAN_PHASE_ERROR; /* failure */
- }
-
- *chopsubdir='.'; /* don't vandalise savepath */
- chopsubdir = strchr((char *)((unsigned int)chopsubdir + 1), '.'); /* find end of next subdirectory */
- }
- }
-
- /* time to save */
- {
- _kernel_oserror *err;
-
- assert(scan_data->output_type == FILETYPE_MAPTILES || scan_data->output_type == FILETYPE_PLANETS || scan_data->output_type == FILETYPE_SPRITE);
- if(scan_data->output_type != FILETYPE_SPRITE)
- err = save_compressedM(scan_data->savepath, scan_data->output_type, &scan_data->output_buffer, time_up, &scan_data->thread_state);
- else
- err = save_fileM(scan_data->savepath, FILETYPE_SPRITE, &scan_data->output_buffer, time_up, &scan_data->thread_state, true);
-
- if(err != NULL) {
- err_report(err->errnum, msgs_lookup_sub1("SaveFail", err->errmess));
- return SCAN_PHASE_ERROR; /* failure */
- }
- }
- if(scan_data->thread_state == NULL) {
- /* Have finished saving data */
- #ifndef NDEBUG
- _kernel_oscli("report Have finished saving data");
- #endif
- /* deallocate memory for output buffer */
- flex_free((flex_ptr)&scan_data->output_buffer);
-
- /* Update count of files output */
- scan_data->numoutput++;
- {
- char num[16];
- #ifndef OLD_SCL_STUBS
- snprintf(num, sizeof(num), "%d", scan_data->numoutput);
- #else
- sprintf(num, "%d", scan_data->numoutput);
- #endif
- RE(button_set_value(0, scan_data->window_id, SCAN_CONVERTED, num))
- }
-
- if(scan_data->input_type == FILETYPE_MAPTILES)
- return SCAN_PHASE_SAVEANIMS; /* extra phase! */
- else
- return SCAN_PHASE_SCANNING; /* success */
- }
- else {
- /* We will have to come back another time */
- //unsigned int perc;
- #ifndef NDEBUG
- _kernel_oscli("report Saving incomplete");
- #endif
- //if(scan_data->output_type != FILETYPE_SPRITE)
- // perc = get_comp_perc(&scan_data->thread_state);
- //else
- // perc = get_loadsave_perc(&scan_data->thread_state);
- return SCAN_PHASE_SAVE; /* success */
- }
- }
-
-